package extract.knowledge.concept;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanTransaction;
import common.dao.couchdb.CouchDBKGFactory;
import common.model.knowledge.ConceptDoc;
import extract.config.ParameterConfig;
import extract.helper.TransactionHelper;
import org.ektorp.CouchDbConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import common.dao.gremlin.TitanGraphDao;

import javax.inject.Inject;
import java.util.List;
import java.util.Random;

/**
 * Created by Common on 8/1/16.
 */
public class ConceptBatchMode {
    final Logger logger = LoggerFactory.getLogger(ConceptBatchMode.class);

    private CouchDBKGFactory couchdb;
    private CouchDbConnector concept_con;

    private TitanGraphDao titandb;
    private TitanGraph graph;

    private ConceptTransformer transformer;


    @Inject
    public ConceptBatchMode(
            CouchDBKGFactory couchdb,
            TitanGraphDao titandb
    ){
        this.couchdb = couchdb;
        this.concept_con = this.couchdb.getConceptCon();

        this.titandb = titandb;
        this.graph = this.titandb.getTitanGraph();

        this.transformer = new ConceptTransformer(this.titandb);

    }



    /**************************
     *
     * @param label
     * @param name
     * @return
     */
    public String validLabel(TextNode label, TextNode name){
        if(label == null && name == null)
            return null;
        else if(label != null)
            return label.asText();
        else
            return name.asText();
    }


    /****************************
     *
     * @throws Exception
     */
    public void testTravelsalCouchdb() {
        List<String> ids = this.concept_con.getAllDocIds();
        /*
        eg:
        http://162.105.180.15:15984/_utils/document.html?kgmeta/concept-1000
         */
        Random rdm = new Random();
        int base = rdm.nextInt(14);
        int index = 0;
        for(String id : ids){
            index += 1;
            if(index % base != 1) continue;
            ObjectNode obj = concept_con.get(ObjectNode.class , id);
            TextNode _id = (TextNode)obj.get("_id");
            //System.out.println("__id  == " +  obj.get("_id").asText());
            if(_id==null || !id.equals(_id.asText()) ){
                logger.error("invalid _id = " + _id.asText() + " , for id = " + id);
                logger.error("Invalid _id!");
            }
            TextNode label = (TextNode)obj.get("label");
            TextNode name = (TextNode)obj.get("name");
            ArrayNode types = (ArrayNode)obj.get("types");
            ArrayNode sub_classes = (ArrayNode)obj.get("sub_classes");
            ArrayNode instances = (ArrayNode)obj.get("instances");
            ArrayNode properties = (ArrayNode)obj.get("properties");
            String validlabel = validLabel(label,name);
            if(validlabel ==null || validlabel.equals("")) {
                logger.error("empty label or name!");
                continue;
            }
            System.out.println("+++++");
            //System.out.println(obj.toString());
            System.out.println("id  = " + id);
            System.out.println("_id = " + _id.asText());
            System.out.println("label = " + label.asText());
            System.out.println("name = " + name.asText());
            System.out.println("types = " + types);
            System.out.println("sub_classes = " + sub_classes);
            System.out.println("instances = " + instances);
            System.out.println("properties = " + properties);
            /*
            for(ObjectNode node : types){

            }
            */
            System.out.println("-----");
            System.out.println();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }


    public void travelsalConceptDB(){
        List<String> ids = this.concept_con.getAllDocIds();
        int index = 0;
        int base = ParameterConfig.Knowledge.travelsalInterval;
        int sleep = ParameterConfig.Knowledge.travelsalSleep;  //毫秒
        TitanTransaction tx = null;
        for(String couch_id : ids){
            //if(index > 20) break;
            if(index % base == 0){
                tx = graph.newTransaction();
            }

            try {
                ConceptDoc concept_doc = this.concept_con.get(ConceptDoc.class, couch_id);
                this.transformer.transformConcept(concept_doc);
            }
            catch (Exception e){
                logger.error("[travelsalConceptDB] Exception for id = " + couch_id + ", ignore, continue...");
                // throw e;
                logger.error( e.toString() );
                tx.commit();
                TransactionHelper.GCAndSleep(sleep);
                if(index % base < base-1 && index < ids.size()-1 )
                    tx = graph.newTransaction();
                continue;
            }

            if(index % base == base-1 || index == ids.size()-1 ){
                tx.commit();
                logger.info("[travelsalConceptDB] committed until " + couch_id);
                TransactionHelper.GCAndSleep(sleep);
            }
            index += 1;
        }
    }

    public void createSchemaIndex(){
        ConceptManagement manage = new ConceptManagement( this.graph );
        manage.runBaseManagement();
    }



    public void run(){
        createSchemaIndex();
        logger.info("[ConceptBatch_Run] createSchemaIndex  success!");
        travelsalConceptDB();
        logger.info("[ConceptBatch_Run] travelsalConceptDB finished!");
    }



    /*****************************
     *
     * @param args
     */
    public static void main(String[] args){

        ConceptBatchMode batch = new ConceptBatchMode(new CouchDBKGFactory(), new TitanGraphDao());

        //batch.createSchemaIndex();

        //batch.travelsalConceptDB();

        batch.run();

        System.out.println("[batch concept trans] success!");
    }


}
